#pragma once
#include <iostream>
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "Protocol.hpp"
#include <functional>
using namespace log_ns;
using namespace socket_ns;
// 主要是进行io服务
// using service_io_t = std::function<void(SockSPtr, const InetAddr &)>;


//定义一个函数对象：返回值是std::shared_ptr<Response>、参数是：std::shared_ptr<Request>
//专门做任务处理：将一个结构化的请求，变成一个结构化的响应
using process_t = std::function<std::shared_ptr<Response>(std::shared_ptr<Request>)>;

class IOService
{
public:
    IOService(process_t process): _process(process)
    {
    }
    void IOExecute(SockSPtr sock, InetAddr &addr)
    {
        std::string packagestreamqueue;
        // 长服务
        while (true)
        {
            // 1.负责读取
            ssize_t n = sock->Recv(&packagestreamqueue);
            if (n <= 0)
            {
                LOG(INFO, "client %s quit or recv error\n", addr.AddrStr().c_str());
                break;
            }
            std::cout <<"==========================================="<< std::endl;
            std::cout << "packagestreamqueue: \n" << packagestreamqueue << std::endl;
            //能保证我们读取到的是一个完整的报文吗？不能！
            // 2.报文解析，提取报文和有效载荷
            std::string package = Decode(packagestreamqueue);
            if(package.empty()) continue;
            //现在能保证我们读取到的是一个完整的jsonstr
            //反序列化做处理
            auto req = Factory::BuildRequestDefault();

            std::cout << "package: \n" << package << std::endl;

            // 3.做反序列化
            req->Deserialize(package);

            // 4.业务处理
            //做业务处理,我想通过一个请求得到应答
            auto resp = _process(req);

            // 5.构建序列化应答
            //给别人响应回去
            std::string respjson;
            //先序列化
            resp->Serialize(&respjson);
            std::cout << "respjson: \n" << respjson << std::endl;
            
            // 6.添加len长度报头
            //携带报文的应答集成串
            respjson = Encode(respjson);
            std::cout << "respjson add header done: \n" << respjson << std::endl;
            
            //7.响应回去
            //再发出去
            sock->Send(respjson);
        }
    }
    ~IOService()
    {
    }
private:
    process_t _process;
};